package org.zero.manager;

import java.util.Arrays;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

/**
 * @author Zero
 */
@Component
@Aspect
@Slf4j
public class MyCacheAdvice {

    @Autowired
    private MyCache cache;

    @Pointcut("execution(* org.zero.service.impl.*.*(..))")
    private void pointcut() {
    }

    @Before("pointcut()")
    public void beforeLog() {
        System.out.println("前置通知日志");
    }

    @AfterReturning("pointcut()")
    public void returnLog() {
        System.out.println("后置通知日志");
    }

    /**
     * 环绕增强的方法
     * ProceedingJoinPoint 接入点
     * 通过接入点，可以取到原业务类的相关信息
     *
     * @param jp
     * @return
     * @throws Throwable
     */
    @Around("pointcut()")
    public Object caching(ProceedingJoinPoint jp) throws Throwable {
        // 目标对象
        Object target = jp.getTarget();
        // 目标参数
        Object[] args = jp.getArgs();

        // 业务方法返回对象
        Object obj = null;

        // 拼接缓存的key
        String key = target.getClass().getName() + ":" + Arrays.toString(args);
        if ((obj = cache.getCache(key)) != null) {
            // 缓存命中
            return obj;
        }

        // 缓存未命中
        // 让原业务类方法运行并获取返回值
        obj = jp.proceed();
        // 后置增强
        // 将查询结果存入缓存
        cache.addCache(key, obj);
        // 结果返回给调用者
        return obj;

    }
}
